package com.basker.pisces.utils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.util.StringUtils;

import static java.util.regex.Pattern.CASE_INSENSITIVE;

/**
 * emial格式校验器，参考了hibernate验证框架里的实现
 *
 * @author hangwen
 */
public class EmailUtils {
    private static final String LOCAL_PART_ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~\u0080-\uFFFF-]";
    private static final String LOCAL_PART_INSIDE_QUOTES_ATOM = "([a-z0-9!#$%&'*.(),<>\\[\\]:;  " +
            "@+/=?^_`{|}~\u0080-\uFFFF-]|\\\\\\\\|\\\\\\\")";
    private static final Pattern LOCAL_PART_PATTERN = Pattern
            .compile(
                    "(" + LOCAL_PART_ATOM + "+|\"" + LOCAL_PART_INSIDE_QUOTES_ATOM + "+\")" + "(\\." + "("
                            + LOCAL_PART_ATOM + "+|\"" + LOCAL_PART_INSIDE_QUOTES_ATOM + "+\")" + ")*",
                    CASE_INSENSITIVE);
    private static final String DOMAIN_CHARS_WITHOUT_DASH = "[a-z\u0080-\uFFFF0-9!#$%&'*+/=?^_`{|}~]";
    private static final String DOMAIN_LABEL = "(" + DOMAIN_CHARS_WITHOUT_DASH + "-*)*" + DOMAIN_CHARS_WITHOUT_DASH
            + "+";
    private static final String DOMAIN = DOMAIN_LABEL + "+(\\." + DOMAIN_LABEL + "+)*";

    /**
     * Regular expression for the domain part of an email address (everything after
     * '@')
     */
    private static final Pattern EMAIL_DOMAIN_PATTERN = Pattern.compile(DOMAIN, CASE_INSENSITIVE);

    public static boolean isValid(String value) {
        if (StringUtils.isEmpty(value)) {
            return false;
        }

        int splitPosition = value.lastIndexOf('@');

        if (splitPosition < 0) {
            return false;
        }

        String localPart = value.substring(0, splitPosition);
        String domainPart = value.substring(splitPosition + 1);

        if (!isValidEmailLocalPart(localPart)) {
            return false;
        }

        return isValidEmailDomainAddress(domainPart);
    }

    private static boolean isValidEmailDomainAddress(String domainPart) {
        if (domainPart.endsWith(".")) {
            return false;
        }

        Matcher matcher = EMAIL_DOMAIN_PATTERN.matcher(domainPart);
        if (!matcher.matches()) {
            return false;
        }

        return true;
    }

    private static boolean isValidEmailLocalPart(String localPart) {
        Matcher matcher = LOCAL_PART_PATTERN.matcher(localPart);
        return matcher.matches();
    }
}
